package com.kl.turn;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 交替输出await/signal
 * 注意：只有获得锁对象，才能调用锁对象中的API唤醒阻塞队列中的线程
 */
@Slf4j
public class AlternateTest2 extends ReentrantLock {
    private final int loopNum;

    public AlternateTest2(int loopNum) {
        this.loopNum = loopNum;
    }

    /**
     * @param num           需要打印的字符串
     * @param condition     当前等待的休息室
     * @param nextCondition 需要唤醒的休息室
     */
    public void print(String num, Condition condition, Condition nextCondition) {
        for (int i = 0; i < loopNum; i++) {
            this.lock();
            try {
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                log.info(num);
                nextCondition.signal(); //唤醒休息室里的线程
            } finally {
                this.unlock(); //锁释放后被唤醒的线程才能执行
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        AlternateTest2 alternate = new AlternateTest2(5);
        Condition t1 = alternate.newCondition();
        Condition t2 = alternate.newCondition();
        Condition t3 = alternate.newCondition();
        new Thread(() -> {
            alternate.print("A", t1, t2);
        }, "线程t1").start();
        new Thread(() -> {
            alternate.print("B", t2, t3);
        }, "线程t2").start();
        new Thread(() -> {
            alternate.print("C", t3, t1);
        }, "线程t3").start();

        Thread.sleep(1000);
        //上面三个线程都进入了自己对应的休息室中阻塞,由主线程作为媒介唤醒其中一个休息室中的线程开始循环打印
        try {
            alternate.lock();
            t1.signal();
        } finally {
            alternate.unlock();
        }
    }
}